;Flash Writing code written to be easily located in any spot within WRAM.
;It is recommended that you verify the data to be saved is actually different from what is in flash, before you actually write to the flash
;as flash chips have a finite number of erase/write cycles,  Usually 100,000 for the chips used in the games to be written.
;
;A sector needs to be erased before it is written to.
;If the sector is not erased first, the data written will be a bitwise AND of the existing data and the data you wish to write, which may
;not be the desired behavior. :)
;
;Also be careful that you don't accidently target sectors where your code is stored, or you will brick your code. :)
;For obvious reasons, the Chip erase command is not included in this code.
	
	
FlashRamPage	.EQU	$0100	;Needs to be located in WRAM.

TargetBank		.EQU	$F8		;These variables need to be located in the Zero Page, due to the need for Indirect addressing.
TargetAddress	.EQU	$F9
TargetAddress_h	.EQU	$FA
SourceAddress	.EQU	$FB
SourceAddress_h	.EQU	$FC
ReturnBank		.EQU	$FD

;Some macro defines for calling the functions.  You must include this file in whatever bank this code is going to be run from, then make the calls to
;these macros.
	
CallWriteVerify	.macro	;Internally used by CallEraseSector and CallWriteByte.
	
	.endm
	
;CallSoftwareIdentify - Returns Chip Manufacturer and Chip ID information. THis can be used
;to determine how much free space you have, if for example, your game only uses 128KB, but is flashed
;to a 256KB or 512KB flash chip.  The chip manufacturer for most of the installed chips is likely to
;be 0xBF, and Chip ID be 0xB5 for 128KB, 0xB6 for 256KB or 0xB7 for 512KB.
;
;This is the one command you can attempt to execute to determine if flash saving is enabled on the cart or not.
;Just make sure you don't have 0xBF in address 0, and 0xB5/0xB6/0xB7 in address 1, as these are the addresses this command
;actually reads.
CallSoftwareIdentify	.macro	;Uses ReturnBank. A destroyed, X = Chip Manufacturer, Y = Chip ID
	JSR (FlashRamPage+(SoftwareIdentify-WriteVerify))
	.endm
	
;CallEraseSector - Used to erase a 4KB sector of flash.
;Erasing sets every single byte in that sector to 0xFF.
;If there are any values you wish to save, read them out before 
;erasing the sector.
CallEraseSector	.macro	;Uses TargetBank, TargetAddress, ReturnBank. A & Y destroyed.
	JSR (FlashRamPage+(EraseSector-WriteVerify))
	.endm
	
;CallWriteByte - Used to write a byte to flash.
;The byte actually written is a logical bitwise AND of the desired value to write, and the value currently stored in flash.
;Because of this, writes will progress from 0xFF towards 0x00.  Flash bits can only be cleared with this function.
CallWriteByte	.macro	;Byte to Write in A, Address is TargetAddress+Y. Uses TargetBank, TargetAddress, ReturnBank.
	JSR (FlashRamPage+(WriteByte-WriteVerify))
	.endm
	
;JmpExitBank - mostly needed only for flash saving hacks. Put the bank to exit with on the A register, then use this macro.
JmpExitBank	.macro	;Bank to switch to on return in A register.
	JMP (FlashRamPage+(ReturnToBank-WriteVerify))
	.endm

	
WriteVerify:
	LDA [TargetAddress],Y
	CMP [TargetAddress],Y
	BNE WriteVerify
	RTS
	
EraseSector:
	LDA #$01
	STA $C000
	LDA #$AA
	STA $9555
	LDA #$00
	STA $C000
	LDA #$55
	STA $AAAA
	LDA #$01
	STA $C000
	LDA #$80
	STA $9555
	LDA #$01
	STA $C000
	LDA #$AA
	STA $9555
	LDA #$00
	STA $C000
	LDA #$55
	STA $AAAA
	LDA TargetBank
	STA $C000
	LDY #$00
	LDA #$30
	STA [TargetAddress],Y
	JSR FlashRamPage
	LDA ReturnBank
ReturnToBank:
	STA $C000
	RTS
	
WriteByte:
	PHA
	LDA #$01
	STA $C000
	LDA #$AA
	STA $9555
	LDA #$00
	STA $C000
	LDA #$55
	STA $AAAA
	LDA #$01
	STA $C000
	LDA #$A0
	STA $9555
	LDA TargetBank
	STA $C000
	PLA
	STA [TargetAddress],Y
	JSR FlashRamPage
	LDA ReturnBank
	STA $C000
	RTS
	
SoftwareIdentify:
	LDA #$80
	STA TargetAddress_h
	LDA #$01
	STA TargetAddress
	STA $C000
	LDA #$AA
	STA $9555
	LDA #$00
	STA $C000
	LDA #$55
	STA $AAAA
	LDA #$01
	STA $C000
	LDA #$90
	STA $9555
	JSR FlashRamPage
	LDA $8000
	TAX
	LDA $8001
	TAY
	LDA #$F0
	STA $8000
	JSR FlashRamPage
	LDA ReturnBank
	STA $C000
	RTS

;Call this routine to copy all the flash related functions into ram.
CopyFlashRoutine:
	LDY #$00
CopyFlashRoutineLoop:
	LDA WriteVerify,Y
	STA FlashRamPage,Y
	INY
	CPY #(CopyFlashRoutine-WriteVerify)
	BNE CopyFlashRoutineLoop
	RTS
	

